There are two basic plotting strategies for complex networks: the traditional graphical representation, a static view of the topology and structure, and the dynamic visualizations taking advantage of interactivity provided by web access or html widgets (e.g., java-based packages).
There are many functions in R to plot networks, especially unipartite networks. Bipartite networks can readily be plotted with the bipartite package function plotweb (1).
Recently, dynamic extensions of this kind of plot hav been included in package bipartiteD3 (2) (see below).
library(bipartite)
data("Safariland")
plotweb(Safariland)
A function for plotting this type of ‘railway’ diagram is included in my package ggbipart for ploting bipartite networks (see below).
ggbipart, an R package for plotting bipartite networksThis is a series of R functions aimed to plot bipartite networks within the ggplot2 environment. The library relies heavily on code developed by Francois Briatte for the ggnet library.
If not already installed, just grab it from my GitHub repo. The install will ask to install dependencies packages if new versions of them are available.
# Install directly from the GitHub repository.
require(devtools)
devtools::install_github("pedroj/bipartite_plots", dependencies= T)
library(ggbipart)
Bipartite networks are a special type of network where nodes are of two distinct types or sets, so that connections (links) only exist among nodes of the different sets.
As in other types of network, bipartite strucures can be binary (only the presence/absence of the links is mapped) or quantitative (weighted), where the links can have variable importance or weight.
To plot, we start with an adjacency or incidence matrix. I’m using matrices that illustrate ecological interactions among species, such as the mutualisttic interactions of animal pollinators and plant flowers. The two sets (modes) of these bipartite netwroks are animals (pollinators) ans plants species.
From any adjacency matrix we can get a network object or an igraph object for plotting and analysis.
Here I plot bipartite networks from their adjacency matrices, i.e., the two-mode networks. The standard way to input an adjacency matrix is from a .txt or a .csv file. Most packages like network, igraph or statnet also accept edge-list archives. These have the form of a three-column array with node1 node2 i or node1 node2 w, where node1 and node2 are two nodes that interact, and ior w are the presence/abscence of interaction (i= 0 o r i= 1) or the edge weight (w) in the case of weighted networks.
network objects# Read data matrices.
# Read a network
# Creating the objects. Example input from the clipboard.
#
# Where data.txt has a weighted adjacency matrix, e.g.,:
# Aa Ab Ac Ba Bb Bc Bd Ca Cb Cc Da
# P1 139 60 9 23 4 104 5 3 5 2 1
# P2 184 26 6 10 3 6 17 11 3 1 0
# P3 131 74 33 36 13 19 0 9 0 1 0
# P4 87 40 38 21 13 0 9 0 1 0 0
# P5 100 42 17 12 4 1 1 0 0 0 0
# P6 21 15 7 0 4 1 0 0 0 0 0
# P7 42 16 3 0 2 0 0 0 0 0 0
# P8 31 8 4 5 1 0 0 1 0 0 0
# P9 46 8 2 0 3 0 0 0 0 0 0
# P10 86 0 0 12 0 2 2 0 0 0 0
# P11 23 8 1 5 0 0 0 0 0 0 0
# P12 13 6 1 1 0 1 0 0 0 0 0
# P13 5 0 1 0 0 0 0 0 0 0 0
# P14 9 1 0 0 0 0 0 0 0 0 0
# Use this to copy from the clipboard, after select/copy the above block.
# # NOT RUN:
# mymat <- read.table(pipe("pbpaste"), header= T, sep= "\t", row.names= 1)
The adjacency matrix is just read from the clipboard as a tab-separated file with header names, and the first column is taken as the row names.
This next example (from F. Briatte code) initializes a dataframe:
# A weighted adjacency matrix. Rows are animal species; columns are plant
# species.
bip= data.frame(P1= c(1, 12, 6, 0),
P2= c(1, 0, 4, 0),
P3= c(1, 7, 3, 12),
row.names= letters[1:4])
bip
This is a function to plot a classic bipartite graph. In the example above we read the dataset from the clipboard. So now we’ll use a direct reading from a file.
#---------------------------------------------------------------------------
# A function for plotting a traditional bipartite graph
# Plot layout coordinates for railway networkplot
# A matrix whose rows contain the x,y coordinates of the vertices of d.
#
source("./code/functions/bip_init_network.R")
source("./code/functions/bip_init_igraph.R")
require(GGally)
## Loading required package: GGally
## Registered S3 method overwritten by 'GGally':
## method from
## +.gg ggplot2
bip_railway <- function (mymat, nodesize=9, label=F) {
# Coords for mode "A"
coordP<- cbind(rep(2,dim(mymat)[1]), seq(1, dim(mymat)[1])+2)
# Coords for mode "P"
coordA<- cbind(rep(4,dim(mymat)[2]), seq(1, dim(mymat)[2])+2)
mylayout<- as.matrix(rbind(coordP, coordA))
#
# Initialize and plot the network with a railway layout.
test.net<- bip_init_network(mymat)
p<- ggnet2(test.net, mode=mylayout, label=label,
size= nodesize, label.size=nodesize/3,
layout.exp=1.5) +
coord_flip()
p
}
#---------------------------------------------------------------------------
#
# Read the matrix again.
mymat <- read.table("./data/data.txt", row.names=1) # Not run.
# Plot layout coordinates for railway networkplot. Input is the
# adjacency matrix.
#
g<- bip_railway(mymat, label=T)
## Loading required package: ggnet
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'ggnet'
g+ coord_flip()
## Coordinate system already present. Adding new coordinate system, which will replace the existing one.
To use the mode of the nodes as the basis for their colors, all the user has to do is to pass the color= “mode” argument, and then to style the “actor” and “event” values:
Label the edge weights directly into the edges of the graph.
source("./code/functions/bip_ggnet.R")
source("./code/functions/bip_edgewt.R")
bip= data.frame(P1= c(1, 12, 6, 0),
P2= c(1, 0, 4, 0),
P3= c(1, 7, 3, 12),
row.names= letters[1:4])
col= c("A"= "grey80", "P"= "gold2")
bip.net<- bip_init_network(as.matrix(bip))
## Loading required package: ggnet
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'ggnet'
bip_ggnet(bip.net, as.matrix(bip),
# color= "mode", palette = col,
edge.label = "weights",
label= TRUE)
## Warning: Duplicated override.aes is ignored.
These are two example datasets of well-sampled plant-frugivore interaction networks from S Spain, read in the usual way. I also read the attributes files, i.e., data.frames with node characteristics that can be used later to label the nodes.
Note that the matrices are read as data.frames. This is useful for later analysis. Yet it is very handy to have also these adjacency matrices in matrix form.
# The Nava de las Correhuelas dataset.
nch<- read.table("./data/sdw01_adj_fru.csv",
header=T, sep=",", row.names=1,
dec=".", na.strings="NA")
## Node attributes
nch_attr<- read.table("./data/sdw01_node_attributes.csv",
header=T, sep=",",
dec=".", na.strings="NA")
# The Hato Raton dataset.
hr<- read.table("./data/sdw02_adj_fru.csv",
header=T, sep=",", row.names=1,
dec=".", na.strings="NA")
## Node attributes
hr_attr<- read.table("./data/sdw01_node_attributes.csv",
header=T, sep=",",
dec=".", na.strings="NA")
Node attributes include different variables characterizing each individual node. These values can later be passed to the bip_ggnet funtions to modify graph properties of nodes.
glimpse(nch_attr)
## Rows: 62
## Columns: 26
## $ class <chr> "Magnoliopsida", "Liliopsida", "Magnoliopsida", "Magnoliopsida…
## $ order <chr> "Rosales", "Arales", "Ranunculales", "Rosales", "Rosales", "Eu…
## $ family <chr> "Rosaceae", "Araceae", "Berberidaceae", "Rosaceae", "Rosaceae"…
## $ genus <chr> "Amelanchier", "Arum", "Berberis", "Cotoneaster", "Crataegus",…
## $ species <chr> "Amelanchier.ovalis", "Arum.italicum", "Berberis.vulgaris", "C…
## $ spcode <chr> "Amova", "Arita", "Bevul", "Cogra", "Crmon", "Dalau", "Hehel",…
## $ w <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ g <dbl> 7.3, 9.2, 5.5, 7.0, 9.3, 6.4, 8.4, 8.6, 12.9, 11.5, 8.7, 8.0, …
## $ f <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ a <dbl> 0.00010, 0.66000, 14.52000, 0.14500, 0.84500, 0.00011, 1.96000…
## $ geog <int> 4, 7, 14, 6, 14, 10, 6, 13, 4, 8, 8, 9, 4, 5, 3, 5, 5, 10, 6, …
## $ ph <dbl> 1.0, 0.5, 3.0, 1.0, 6.0, 1.0, 3.0, 10.0, 2.0, 7.0, 9.0, 1.5, 1…
## $ pp <dbl> 0.3333, 0.2121, 0.2424, 0.3030, 0.1515, 0.2727, 0.2424, 0.3333…
## $ ps <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ pa <dbl> 0.1515, 0.1515, 0.1212, 0.0909, 0.1515, 0.2424, 0.0606, NA, 0.…
## $ pu <dbl> 0.4242, 0.5758, 0.2121, 0.5455, 0.0303, 0.3636, 0.4545, 0.5152…
## $ hab <chr> "climax", "climax", "climax", "climax", "climax", "climax", "c…
## $ diet <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ forag <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ noct <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ nativ <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
## $ frlen <dbl> 7.0, 11.1, 10.4, 7.5, 12.1, 9.4, 7.2, 8.2, 11.3, 9.9, 7.3, 7.6…
## $ fleshy <chr> "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes",…
## $ seedm <dbl> 0.003, 0.038, 0.020, 0.025, 0.124, 0.022, 0.016, 0.011, 0.062,…
## $ height <dbl> 1.9, 0.3, 1.2, 1.3, 4.0, 1.2, 3.0, 0.6, 2.8, 0.6, 0.6, 3.0, 1.…
## $ grwform <chr> "shrub", "herb", "shrub", "shrub", "tree", "shrub", "liana", "…
glimpse(hr_attr)
## Rows: 62
## Columns: 26
## $ class <chr> "Magnoliopsida", "Liliopsida", "Magnoliopsida", "Magnoliopsida…
## $ order <chr> "Rosales", "Arales", "Ranunculales", "Rosales", "Rosales", "Eu…
## $ family <chr> "Rosaceae", "Araceae", "Berberidaceae", "Rosaceae", "Rosaceae"…
## $ genus <chr> "Amelanchier", "Arum", "Berberis", "Cotoneaster", "Crataegus",…
## $ species <chr> "Amelanchier.ovalis", "Arum.italicum", "Berberis.vulgaris", "C…
## $ spcode <chr> "Amova", "Arita", "Bevul", "Cogra", "Crmon", "Dalau", "Hehel",…
## $ w <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ g <dbl> 7.3, 9.2, 5.5, 7.0, 9.3, 6.4, 8.4, 8.6, 12.9, 11.5, 8.7, 8.0, …
## $ f <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ a <dbl> 0.00010, 0.66000, 14.52000, 0.14500, 0.84500, 0.00011, 1.96000…
## $ geog <int> 4, 7, 14, 6, 14, 10, 6, 13, 4, 8, 8, 9, 4, 5, 3, 5, 5, 10, 6, …
## $ ph <dbl> 1.0, 0.5, 3.0, 1.0, 6.0, 1.0, 3.0, 10.0, 2.0, 7.0, 9.0, 1.5, 1…
## $ pp <dbl> 0.3333, 0.2121, 0.2424, 0.3030, 0.1515, 0.2727, 0.2424, 0.3333…
## $ ps <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ pa <dbl> 0.1515, 0.1515, 0.1212, 0.0909, 0.1515, 0.2424, 0.0606, NA, 0.…
## $ pu <dbl> 0.4242, 0.5758, 0.2121, 0.5455, 0.0303, 0.3636, 0.4545, 0.5152…
## $ hab <chr> "climax", "climax", "climax", "climax", "climax", "climax", "c…
## $ diet <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ forag <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ noct <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ nativ <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
## $ frlen <dbl> 7.0, 11.1, 10.4, 7.5, 12.1, 9.4, 7.2, 8.2, 11.3, 9.9, 7.3, 7.6…
## $ fleshy <chr> "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes",…
## $ seedm <dbl> 0.003, 0.038, 0.020, 0.025, 0.124, 0.022, 0.016, 0.011, 0.062,…
## $ height <dbl> 1.9, 0.3, 1.2, 1.3, 4.0, 1.2, 3.0, 0.6, 2.8, 0.6, 0.6, 3.0, 1.…
## $ grwform <chr> "shrub", "herb", "shrub", "shrub", "tree", "shrub", "liana", "…
Here I use the function bip_init_network to initialize a few examples of bipartite networks. The function returns a network object. The equivelent fucntion bip_init_igraph returns an igraph (graph) object.
source("./code/functions/bip_init_network.R")
source("./code/functions/bip_init_igraph.R")
nch.net<- bip_init_network(nch) # Network object
## Loading required package: ggnet
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'ggnet'
nch.ig<- bip_init_igraph(nch) # igraph object
hr.net<- bip_init_network(hr) # Network object
## Loading required package: ggnet
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'ggnet'
hr.ig<- bip_init_igraph(hr) # igraph object
# Set colors for each mode
col= c("P"= "#FC9272", "A"= "#9ECAE1")
pp<- bip_ggnet(hr.net, as.matrix(hr),
size=7, shape= "mode", #label= T,
color= "mode", palette= col,
layout.exp= 0.25) +
geom_text(aes(label= network.vertex.names(hr.net)),
color= "black", size= 3) +
theme(legend.position="none") # Hide legend
pp
Another alternative is to pass the node colors directly, with a vector of node colors that has exactly the same length as the number of nodes in the network:
pp1<- bip_ggnet(nch.net, as.matrix(nch),
size= 6, color= "mode", label= T, label.size=2,
palette= c("P"= "indianred3", "A"= "steelblue4")) +
theme(legend.position="none") # Hide legend
pp1
pp2<- bip_ggnet(nch.net, as.matrix(nch),
size= 0,
shape= "mode",
palette= "Set1",
color= "mode",
layout.exp= 0.25) +
geom_point(aes(color= color), size= 8, color= "white") +
geom_point(aes(color= color), size= 8, alpha= 0.5) +
geom_point(aes(color= color), size= 6) +
geom_text(aes(label= network.vertex.names(nch.net)),
color= "black", size= 3.5) + # check_overlap= TRUE
guides(color= FALSE) +
theme(legend.position="none") # Hide legend
## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
pp2
nums<- as.vector(c(1:sum(dim(nch))))
pp3<- bip_ggnet(nch.net, as.matrix(nch),
size= 0,
shape= "mode",
palette= "Set1",
color= "mode",
layout.exp = 0.25) +
geom_point(aes(color= color), size= 10, color= "white") +
geom_point(aes(color= color), size= 10, alpha= 0.5) +
geom_point(aes(color= color), size= 8) +
geom_text(aes(label= nums),
color= "white", size= 3.5, fontface="bold") +
guides(color= FALSE) +
theme(legend.position="none") # Hide legend
## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
pp3
# Input the dataset, as adjacency matrix
pm.disp<- read.table("./data/pmah_disp.txt",
na="NA", sep="\t", dec=".", header= TRUE)
pm.attr<- read.table("./data/pmah_attr.txt",
na="NA", sep="\t", dec=".", header= TRUE)
# Saving
save(pm.disp, file="./data/pm.disp.RData")
pm.disp.mat<- as.matrix(pm.disp[,2:22])
row.names(pm.disp.mat)<- pm.disp$X
pru.disp.net<- bip_init_network(pm.disp.mat)
## Loading required package: ggnet
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'ggnet'
pru.disp.net %e% "nweights"<- 50*(network::get.edge.attribute(pru.disp.net, "weights"))
# Set colors for each mode to setup a palette.
myggnet<- function(net, edge.size= "weights") { # A net object
col= c("A"= "lightblue", "P"= "gold")
pp<- ggnet2(net, size= 6, palette= col, color= "mode",
label.size=3, label= T, shape= "mode",
edge.label= NULL, edge.size= edge.size,
edge.alpha= 0.5, layout.exp= 0)
return(pp)
}
myggnet(pru.disp.net,
edge.size= 0.025*(network::get.edge.attribute(pru.disp.net, "weights")))
## Warning: Duplicated override.aes is ignored.
Here we add a value for interaction strength among nodes, so that our networks gets infoermation about the interaction weights. Note that these values are added to the link attributes.
# Load package
require(networkD3)
## Loading required package: networkD3
pm.disp.el<- read.table("./data/pru.disp.el.txt",
na="NA", sep="\t", dec=".", header= TRUE)
# Convert to object suitable for networkD3
pm.disp.el[,1]<- as.character(pm.disp.el[,1])
pm.disp.el[,2]<- as.character(pm.disp.el[,2])
pm.disp.el<- as.matrix(pm.disp.el)
# The graph
pm.disp.g<- graph.edgelist(pm.disp.el[,1:2], directed=FALSE)
E(pm.disp.g)$weight<- as.numeric(pm.disp.el[,3])
pm.disp.d3 <- igraph_to_networkD3(pm.disp.g)
# pm.disp.d3$nodes$group<- c("A","P","A","A")
# Weighted network
# Plot
pm.disp.nodes<- as.data.frame(pm.disp.d3$nodes$name)
pm.disp.nodes$group<- c(rep("F",22),rep("P",18))
colnames(pm.disp.nodes)<- c("name", "group")
forceNetwork(Links = pm.disp.d3$links, Nodes = pm.disp.nodes,
Source = 'source', Target = 'target', NodeID = 'name',
Value='value', Group = "group",
linkDistance = JS("function(d){return d.value * 15}"),
linkWidth = JS("function(d) { return Math.sqrt(d.value)/3; }"),
fontFamily = "sans-serif", fontSize= 12, legend=T,
bounded=T, opacityNoHover= 0.5, charge=-30,
height= 600, width= 600, zoom = TRUE, opacity = 0.65)
The package bipartiteD3 can also be used for easily interact with bipartite networks.
# Plot with bipartiteD3
require(bipartiteD3)
## Loading required package: bipartiteD3
bipartite_D3(Safariland, PrimaryLab = 'Flowers',
SecondaryLab = 'Pollinators',
colouroption = 'brewer',
BrewerPalette ='Dark2')
## Warning in RColorBrewer::brewer.pal(n = length(ToColour), name = BrewerPalette): n too large, allowed maximum for palette Dark2 is 8
## Returning the palette you asked for with that many colors
nch.m<- as.matrix(nch)
bipartite_D3(nch.m, PrimaryLab = 'Plants',
SecondaryLab = 'Frugivores',
colouroption = 'brewer',
BrewerPalette ='Dark2')
## Warning in RColorBrewer::brewer.pal(n = length(ToColour), name = BrewerPalette): n too large, allowed maximum for palette Dark2 is 8
## Returning the palette you asked for with that many colors
sessionInfo()
## R version 4.0.3 (2020-10-10)
## Platform: x86_64-apple-darwin17.0 (64-bit)
## Running under: macOS Big Sur 10.16
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## attached base packages:
## [1] stats graphics grDevices datasets utils methods base
##
## other attached packages:
## [1] bipartiteD3_0.3.0 networkD3_0.4 GGally_2.1.2
## [4] intergraph_2.0-2 igraph_1.2.7 bipartite_2.16
## [7] vegan_2.5-7 lattice_0.20-44 permute_0.9-5
## [10] statnet_2019.6 tsna_0.3.5 sna_2.6
## [13] statnet.common_4.5.0 ergm.count_4.0.2 tergm_4.0.2
## [16] networkDynamic_0.11.0 ergm_4.1.2 network_1.17.1
## [19] knitr_1.36 devtools_2.4.3 usethis_2.0.1
## [22] summarytools_0.9.9 forcats_0.5.1 stringr_1.4.0
## [25] dplyr_1.0.7 purrr_0.3.4 readr_1.4.0
## [28] tidyr_1.1.4 tibble_3.1.5 ggplot2_3.3.5
## [31] tidyverse_1.3.1 here_1.0.1
##
## loaded via a namespace (and not attached):
## [1] colorspace_2.0-2 pryr_0.1.4 ellipsis_0.3.2
## [4] rprojroot_2.0.2 base64enc_0.1-3 fs_1.5.0
## [7] rstudioapi_0.13 farver_2.1.0 remotes_2.4.0
## [10] fansi_0.5.0 lubridate_1.7.10 xml2_1.3.2
## [13] codetools_0.2-18 splines_4.0.3 cachem_1.0.5
## [16] robustbase_0.93-8 pkgload_1.2.1 spam_2.7-0
## [19] jsonlite_1.7.2 broom_0.7.7 cluster_2.1.2
## [22] dbplyr_2.1.1 compiler_4.0.3 httr_1.4.2
## [25] backports_1.2.1 assertthat_0.2.1 Matrix_1.3-4
## [28] fastmap_1.1.0 cli_3.1.0 htmltools_0.5.2
## [31] prettyunits_1.1.1 tools_4.0.3 dotCall64_1.0-1
## [34] coda_0.19-4 gtable_0.3.0 glue_1.5.0
## [37] maps_3.4.0 Rcpp_1.0.8 rle_0.9.2
## [40] jquerylib_0.1.4 cellranger_1.1.0 vctrs_0.3.8
## [43] nlme_3.1-152 xfun_0.28 ps_1.6.0
## [46] testthat_3.0.2 trust_0.1-8 rvest_1.0.0
## [49] lifecycle_1.0.1 DEoptimR_1.0-9 MASS_7.3-54
## [52] scales_1.1.1 hms_1.1.1 parallel_4.0.3
## [55] RColorBrewer_1.1-2 fields_12.5 yaml_2.2.1
## [58] gridExtra_2.3 memoise_2.0.0 downloader_0.4
## [61] pander_0.6.4 sass_0.4.0 reshape_0.8.8
## [64] stringi_1.7.5 highr_0.9 desc_1.3.0
## [67] checkmate_2.0.0 pkgbuild_1.2.0 rlang_0.4.12
## [70] pkgconfig_2.0.3 matrixStats_0.59.0 evaluate_0.14
## [73] lpSolveAPI_5.5.2.0-17.7 htmlwidgets_1.5.4 rapportools_1.0
## [76] processx_3.5.2 tidyselect_1.1.1 plyr_1.8.6
## [79] magrittr_2.0.1 R6_2.5.1 magick_2.7.2
## [82] generics_0.1.1 DBI_1.1.1 pillar_1.6.4
## [85] haven_2.4.1 withr_2.4.2 mgcv_1.8-36
## [88] modelr_0.1.8 crayon_1.4.2 utf8_1.2.2
## [91] rmarkdown_2.11 viridis_0.6.2 grid_4.0.3
## [94] readxl_1.3.1 callr_3.7.0 reprex_2.0.0
## [97] digest_0.6.28 r2d3_0.2.5 munsell_0.5.0
## [100] viridisLite_0.4.0
## [ reached getOption("max.print") -- omitted 3 entries ]
Licensing Creative Commons License
Licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
2018 - Pedro Jordano